package com.example.springmvcinterview.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.metrics.ApplicationStartup;
import org.springframework.core.metrics.StartupStep;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.nodes.Tag;

import java.time.Duration;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;

/**
 * @Author : 叶荻风
 * @create : 2024/12/10 17:28
 */
@Component
public class LoggingApplicationStartup implements ApplicationStartup {


    private static final Logger logger = LoggerFactory.getLogger(LoggingApplicationStartup.class);

    @Override
    public StartupStep start(String name) {
        return new LoggingStartupStep(name);
    }

    private static class LoggingStartupStep implements StartupStep {

        private final String name;
        private final long id;
        private final Long parentId;
        private final Instant startTime;
        private Instant endTime;
        private final Map<String, String> tags = new HashMap<>();

        public LoggingStartupStep(String name) {
            this.name = name;
            this.id = UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
            this.parentId = null; // For simplicity, we're not tracking parent steps here.
            this.startTime = Instant.now();
            logger.info("Starting step [{}], ID: {}, Time: {}", name, id, startTime);
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public long getId() {
            return id;
        }

        @Override
        public Long getParentId() {
            return parentId;
        }

        @Override
        public StartupStep tag(String key, String value) {
            tags.put(key, value);
            return this;
        }

        @Override
        public StartupStep tag(String key, Supplier<String> value) {
            tags.put(key, value.get());
            return this;
        }

        @Override
        public Tags getTags() {
            logger.info("getTags");
            return null;
        }


        @Override
        public void end() {
            this.endTime = Instant.now();
            logger.info("Ending step [{}], ID: {}, Start Time: {}, End Time: {}, Duration: {} ms",
                    name, id, startTime, endTime, Duration.between(startTime, endTime).toMillis());
        }
    }

    // Simple implementation of Tag interface

}